AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
include("shared.lua")

if file.Exists("../lua/entities/base_wire_entity/init.lua") then 
     include("entities/base_wire_entity/init.lua")
end

local maxents = CreateConVar( "harvester_maxents", "5" ) -- max ents to store in the "buffer"
local allowconstraint = CreateConVar( "harvester_allowconstrainedprops", "0" ) -- if set to 1, props/entities which have been constrained will not be allowed to be sucked in
local allowplayers = CreateConVar( "harvester_allowplayers", "1" ) -- if set to 1 players may be sucked in

local DISALLOWED={ -- these entities cannot be sucked up
prop_door_rotating=true,
stargate_atlantis=true,
stargate_sg1=true,
dhd_atlantis=true,
dhd_sg1=true,
prop_ragdoll=true
}

local soundx=Sound("ambient/atmosphere/city_beacon_loop1.wav")

function ENT:Initialize()
	if (!self.Sound) then
 		self.Sound = CreateSound( self.Entity, soundx )
 	end
	util.PrecacheSound("npc/scanner/scanner_electric2.wav")
	self.Entity:SetModel("models/props_c17/pottery03a.mdl")
	self.Entity:PhysicsInit(SOLID_VPHYSICS)
	self.Entity:SetMoveType(MOVETYPE_VPHYSICS)
	self.Entity:SetSolid(SOLID_VPHYSICS)
	self.Entity:SetNetworkedBool("on",false)
	self.Ents={}
	
	if WireAddon then
		self.Inputs = Wire_CreateInputs(self.Entity, { "on", "off", "spit" })
	end
end

function ENT:OnRemove()
	self.Sound:Stop()
	self.Entity:Spit(true)
end

function ENT:TriggerInput(input,value)
	self.Entity:Fire(tostring(input),tostring(value),0)
end

function ENT:AcceptInput(name,activator,caller)
	if name=="on" then
		self.Entity:SetNetworkedBool("on",true)
		self.Sound:Play()
		self.Sound:SetSoundLevel(110)
		self.Sound:ChangeVolume(400,0.1)
		self.Sound:ChangePitch(250,1)
	end
	if name=="off" then
		self.Entity:SetNetworkedBool("on",false)
		self.Sound:Stop()
	end
	if name=="spit" then
		self.Entity:Spit()
	end
end

function ENT:Spit(override)
	local trace = {}
		trace.start = self.Entity:GetPos()
		trace.endpos = self.Entity:GetPos()+self.Entity:GetUp()*1000
		trace.filter = self.Entity
	local e=util.TraceLine( trace )
	local pos=e.HitPos
		for i,v in pairs(self.Ents) do
			if v==NULL or not v:IsValid() then self.Ents[i]=nil return end
					local ed = EffectData()
						ed:SetStart(self.Entity:GetPos())
						ed:SetOrigin(pos)
						util.Effect( "wraithbeam", ed )
						self.Entity:EmitSound("npc/scanner/scanner_electric2.wav",150,200)
				v:SetMoveType(self.Ents[i].MoveType)
				v:SetSolid(self.Ents[i].Solid)
				v:SetColor(self.Ents[i].r,self.Ents[i].g,self.Ents[i].b,self.Ents[i].a)
				v:SetParent(nil)
				v:SetPos(e.HitPos)
				v:SetAngles(Angle(0,0,0))
					
				if self.Ents[i].MoveType==MOVETYPE_VPHYSICS then
					local phys=v:GetPhysicsObject()
					phys:EnableMotion(true)
					phys:Wake()
				end

				if v:IsPlayer() then
					v:UnSpectate()
					v:DrawViewModel(true)
					v:DrawWorldModel(true)
					v:Spawn()
					v:SetColor(255,255,255,255)
					
					for _,n in pairs(self.Ents[i].Weapons) do
						v:Give(n)
					end

				end
				
				local vFlushPoint = e.HitPos - ( e.HitNormal * 512 )
					vFlushPoint = v:NearestPoint( vFlushPoint )
					vFlushPoint = v:GetPos() - vFlushPoint
					vFlushPoint = e.HitPos + vFlushPoint
				v:SetPos(vFlushPoint)
				
				self.Ents[i]=nil
				if not override then return end
		end
end

local function findent(tabl,ent)
	for k,v in pairs(tabl) do
		if v==ent then return true end
	end
	if DISALLOWED[ent:GetClass()] then return true end
	if string.find(ent:GetClass(),"func_") then return true end
	return false
end

function ENT:Think()
	if self.Entity:GetNetworkedBool("on") and #self.Ents<maxents:GetInt() then
			local trace = {}
			trace.start = self.Entity:GetPos()
			trace.endpos = self.Entity:GetPos()+self.Entity:GetUp()*1000
			trace.filter = self.Entity
			local e=util.TraceLine( trace )
			local pos=e.HitPos
		for _,ent in pairs(ents.FindInSphere(pos,100)) do
			if ent~=self.Entity and self.Entity:GetPos():Distance(pos)>110 and not findent(self.Ents,ent) then
				if ent:IsPlayer() and not allowplayers:GetBool() or ent:IsConstrained() and not allowconstraint:GetBool() then else
					if ent:GetPhysicsObject():IsValid() or ent:IsPlayer() and #self.Ents<MAX_ENTS then
							local ed = EffectData()
								ed:SetStart(ent:GetPos())
								ed:SetOrigin(self.Entity:GetPos())
							util.Effect( "wraithbeam", ed )
							self.Entity:EmitSound("npc/scanner/scanner_electric2.wav",150,50)
							-- store information
							local id=#self.Ents+1
							self.Ents[id]=ent
							self.Ents[id].MoveType=ent:GetMoveType()
							self.Ents[id].Solid=ent:GetSolid()
							local r,g,b,a=ent:GetColor()
							self.Ents[id].r=r
							self.Ents[id].g=g
							self.Ents[id].b=b
							self.Ents[id].a=a
							
							-- move etc
							ent:SetPos(self.Entity:GetPos())
							ent:SetColor(0,0,0,0)
							ent:SetSolid(SOLID_NONE)
							ent:SetMoveType(MOVETYPE_NONE)
							ent:SetParent(self.Entity)
							
							if ent:IsPlayer() then
								ent:Spectate( OBS_MODE_CHASE  )
								ent:SpectateEntity( self.Entity )
								ent:DrawViewModel(false)
								ent:DrawWorldModel(false)
								ent.Weapons={}
								for _,w in pairs(ent:GetWeapons()) do
									self.Ents[id].Weapons[_]=w:GetClass()
								end
								ent:StripWeapons()
							end
					end
				end
			end
		end
	end
end